#include "at_cmd_parser.h"
#include <iostream>
#include <chrono>
#include <thread>

at_cmd_parser::at_cmd_parser(const std::string& serial_port)
    : running(false)
{
    if (!serial.open_port(serial_port)) {
        throw std::runtime_error("Failed to open serial port: " + serial_port);
    }
    serial.configure_port(115200, 8, 1, 'N', false);
}

// 启动AT命令处理器
void at_cmd_parser::start() 
{
    running = true;
    send_thread = std::thread(&at_cmd_parser::sending_thread, this);
    recv_thread = std::thread(&at_cmd_parser::receiving_thread, this);
    process_thread = std::thread(&at_cmd_parser::processing_thread, this);
}

// 停止AT命令处理器
void at_cmd_parser::stop() 
{
    running = false;
    if (send_thread.joinable()) send_thread.join();
    if (recv_thread.joinable()) recv_thread.join();
    if (process_thread.joinable()) process_thread.join();
    serial.close_port();
}

// 添加AT命令及其对应的处理函数
void at_cmd_parser::add_command_handler(const std::string& command, std::function<int(const std::string&)> handler)
{
    std::lock_guard<std::mutex> lock(recv_mtx);    //获取数据接收互斥锁
    command_handler[command] = handler;
}

// 发送AT命令（加入发送队列）
void at_cmd_parser::send_at_cmd(const std::string& command) 
{
    at_command cmd = {command, 0, std::chrono::steady_clock::now()};
    {
        //使用 lock_guard 自动管理互斥锁，获取发送互斥锁
        std::lock_guard<std::mutex> lock(send_mtx);
        send_queue.push_back(cmd);
    }    //退出作用域，解锁
    send_cv.notify_one();  // 唤醒发送线程
}

//发送线程，从队列取出数据进行发送
void at_cmd_parser::sending_thread() 
{
    while (running) {
        std::unique_lock<std::mutex> lock(send_mtx);    //获取发送互斥锁
        
        send_cv.wait(lock, [this]() { return !send_queue.empty() || !running; });    //等待发送条件成立

        if (!running) break;

        auto now = std::chrono::steady_clock::now();    //获取当前时间点
        
        //从发送队列里面取出命令，
        for (auto& cmd : send_queue) {
            if (cmd.retries >= max_retries) {
                send_queue.pop_front();    //移除队列第一个数据
                std::cerr << "Max retries reached for command: " << cmd.command << std::endl;
                break;
            }

            serial.send_string_data(cmd.command + "\r\n");

            //命令发送超时
            if (std::chrono::duration_cast<std::chrono::milliseconds>(now - cmd.last_send_time).count() >= timeout_ms) {
                serial.send_string_data(cmd.command + "\r\n");
                cmd.retries++;
                cmd.last_send_time = now;    //记录上一次发送的时间点
                std::cout << "Sending command: " << cmd.command << ", retry: " << cmd.retries << std::endl;
            }
        }
        lock.unlock();    //手动释放发送互斥锁
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

// 接收线程：负责接收串口数据并放入接收队列
void at_cmd_parser::receiving_thread() 
{
    std::string recv_data;
    char recv_data_buff[256];
    int bytes_read = -1;

    while (running) {

        bytes_read = serial.recv_data_poll((unsigned char *)recv_data_buff, 256);  // 从串口接收数据

        if(bytes_read > 0)
        {
            recv_data.assign(recv_data_buff, static_cast<std::string::size_type>(bytes_read));
        }
        

        if (!recv_data.empty()) {
            std::lock_guard<std::mutex> lock(recv_mtx);    //获取接收互斥锁

            //std::cout << "receiving_thread : " << recv_data << std::endl;

            recv_queue.push_back(recv_data);    //放入数据接收队列

            //std::cout << "recv_queue size " << recv_queue.size() << std::endl;

            recv_cv.notify_one();  // 唤醒处理线程
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }

}

// 处理线程：负责从接收队列中取出数据并处理
void at_cmd_parser::processing_thread() 
{
    while (running) 
    {
        std::unique_lock<std::mutex> lock(recv_mtx);    //获取接收互斥锁
        recv_cv.wait(lock, [this]() { return !recv_queue.empty() || !running; });    //等待条件成立

        if (!running) break;

        std::string response = recv_queue.front();    //取出数据
        recv_queue.pop_front();    //移除队列第一个数据
        lock.unlock();    //手动释放互斥锁

        //std::cout << "at cmd response : " << response << std::endl;

        // 匹配并调用命令处理器
        for (const auto& handler : command_handler)
        {
            //std::cout << "handler.first : " << handler.first << std::endl;
            if (response.find(handler.first) != std::string::npos) 
            {
                if(handler.second(response) == 0)  // 执行对应的处理函数
                {
                    if(!send_queue.empty())send_queue.pop_front();    //移除发送队列第一个数据
                }
                break;
            }
        }
    }
}



